cmake_minimum_required(VERSION 3.14)
set(MAIN_PROJECT_NAME "AnimePet")
set(MAIN_PROJECT_VERSION 0.1)
project("${MAIN_PROJECT_NAME}" VERSION ${MAIN_PROJECT_VERSION} LANGUAGES CXX)
set(THRID_PARTY_DIR "${PROJECT_SOURCE_DIR}/3rdParty")
set(THRID_PARTY_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/3rdParty/install")
#include cmake file
include(FetchContent)
set(FETCHCONTENT_UPDATES_DISCONNECTED ON)
include(ExternalProject)
include(./CMake/CubismChecker.cmake)
include(./CMake/TestConfig.cmake)
#config global build settings
if(NOT DEFINED DISABLE_LLD)
    set(DISABLE_LLD OFF)
endif()
# use md to link
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL$<$<CONFIG:Debug>:Debug>")
# try to use lld
find_program(LLD_FOUND lld)
if(LLD_FOUND)
    if(NOT DISABLE_LLD)
            if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
                message("This project will use lld as linker.")
                message("Disable this behavior by setting CMake variable DISABLE_LLD=ON.")
                set(CMAKE_CXX_FLAGS "-fuse-ld=lld ${CMAKE_CXX_FLAGS}")
            endif()
    endif(NOT DISABLE_LLD)
endif(LLD_FOUND)
if(MSVC)
    set(CMAKE_CXX_FLAGS "/MP ${CMAKE_CXX_FLAGS}")
endif()
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# detect architecture.
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(ARCH x86_64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
    set(ARCH x86)
else()
    message(FATAL_ERROR "Neither 32-bit nor 64-bit architecture!")
endif()
#config spine_runtime-cpp
FetchContent_Declare(spine-cpp
    SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rdParty/spine-runtimes-4.0/spine-cpp
)
FetchContent_MakeAvailable(spine-cpp)
#config CubismSdk(live2d sdk)
# Find opengl libraries.
find_package(OpenGL REQUIRED)
# Surpress GLEW and GLFW process.
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
set(BUILD_UTILS OFF CACHE BOOL "" FORCE)
# Config glew
set(GLEW_PROJECT_NAME "glew-2_1_0")
set(GLEW_SOURCE_PATH "${THRID_PARTY_DIR}/${GLEW_PROJECT_NAME}")
FetchContent_Declare(${GLEW_PROJECT_NAME}
    SOURCE_DIR              ${GLEW_SOURCE_PATH}
)
message(STATUS "Configuring glew...")
FetchContent_GetProperties(${GLEW_PROJECT_NAME})
if(NOT ${GLEW_PROJECT_NAME}_POPULATED)
    FetchContent_Populate(${GLEW_PROJECT_NAME})
    if(WIN32)
        add_subdirectory(${GLEW_SOURCE_PATH}/build/cmake)
    endif()
endif()
message(STATUS "Finish!")
# Specify Cubism Framework rendering.
set(FRAMEWORK_SOURCE OpenGL)
# Config framework
add_subdirectory(./3rdParty/CubismSdkForNative-4-r.4/Framework)
# Add rendering definition to framework.
if(WIN32)
    target_compile_definitions(Framework PUBLIC CSM_TARGET_WIN_GL)
elseif(UNIX AND NOT APPLE)
    target_compile_definitions(Framework PUBLIC CSM_TARGET_LINUX_GL)
elseif(APPLE)
    target_compile_definitions(Framework PUBLIC CSM_TARGET_MAC_GL)
else()
    message(FATAL_ERROR "Unsupported OS!")
endif()
# Add include path of GLEW to framework.
target_include_directories(Framework PUBLIC ${GLEW_SOURCE_PATH}/include)
# Link libraries to framework.
target_link_libraries(Framework Live2DCubismCore glew_s)
# Let invalid conversion from 'PROC' {aka 'long long int (*)()'} to 'void*' pass
target_compile_options(Framework PRIVATE $<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:GNU>:-fpermissive>>)
# Find library path.
set(CORE_PATH ${CMAKE_SOURCE_DIR}/3rdParty/CubismSdkForNative-4-r.4/Core)
if(WIN32)
    set(CORE_LIB_SUFFIX ${CORE_PATH}/lib/windows/${ARCH}/${COMPILER})
    set(CORE_DLL_SUFFIX ${CORE_PATH}/dll/windows/${ARCH}/${COMPILER})
elseif(UNIX AND NOT APPLE)
    set(CORE_LIB_SUFFIX ${CORE_PATH}/lib/liunx/x86_64/)
    set(CORE_DLL_SUFFIX ${CORE_PATH}/dll/liunx/x86_64/)
endif()
find_library(Live2DCubismCore
    NAMES Live2DCubismCore Live2DCubismCore.lib Live2DCubismCore.dll
    PATHS ${CORE_DLL_SUFFIX}
)
#config gtest
if(NOT DEFINED USE_TEST)
    set(USE_TEST ON)
endif()
if(NOT DEFINED USE_GTEST)
    set(USE_GTEST OFF)
endif()
if(NOT DEFINED BUILD_GTEST)
    set(BUILD_GTEST ON)
endif()
if(USE_GTEST OR NOT BUILD_GTEST)
    find_package(GTest 1.11.0 REQUIRED)
else()
    set(GTEST_PROJECT_NAME "googletest_1_11_0")
    set(GTEST_SOURCE_PATH "${THRID_PARTY_DIR}/${GTEST_PROJECT_NAME}")
    FetchContent_Declare(${GTEST_PROJECT_NAME}
        SOURCE_DIR             ${GTEST_SOURCE_PATH}
    )
    set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
    set(BUILD_GTEST ON CACHE BOOL "" FORCE)
    set(gtest_build_tests OFF CACHE BOOL "" FORCE)
    set(gtest_build_samples OFF CACHE BOOL "" FORCE)
    message(STATUS "Configuring gtest...")
    FetchContent_MakeAvailable(${GTEST_PROJECT_NAME})
    message(STATUS "Finish!")
endif()
#preconfig global test target
add_custom_target(BuildAndTestAll ${CMAKE_CTEST_COMMAND} -V -C ${CMAKE_CONFIGURATION_TYPES} -j8 --output-on-failure)
# !!maybe_unused!! force cmake output executable to ${PROJECT_SOURCE_DIR}/Test
set_target_properties(BuildAndTestAll PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Test)
set_target_properties(BuildAndTestAll PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/Test)
set_target_properties(BuildAndTestAll PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/Test)
set_target_properties(BuildAndTestAll PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_SOURCE_DIR}/Test)
set_target_properties(BuildAndTestAll PROPERTIES RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${PROJECT_SOURCE_DIR}/Test)
#config qt5
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
#config MainProject
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_C_VISIBILITY_PRESET hidden)
add_subdirectory(./${MAIN_PROJECT_NAME})
